﻿using System;
using System.Web;
using System.Web.Http.Controllers;
using System.Web.Http.Filters;


namespace HMACAuthentication.WebApi.Filters
{
    // <summary>
    /// 自动识别客户端是否支持压缩，如果支持则返回压缩后的数据
    /// Attribute that can be added to controller methods to force content
    /// to be GZip encoded if the client supports it
    /// </summary>
    public class CompressContentAttribute : ActionFilterAttribute
    {
        /// <summary>
        /// Override to compress the content that is generated by
        /// an action method.
        /// </summary>
        /// <param name="filterContext"></param>
        public override void OnActionExecuting(HttpActionContext filterContext)
        {
            GZipEncodePage();
        }

        /// <summary>
        /// Determines if GZip is supported
        /// </summary>
        /// <returns></returns>
        public static bool IsGZipSupported()
        {
            string AcceptEncoding = HttpContext.Current.Request.Headers["Accept-Encoding"];
            if (!string.IsNullOrEmpty(AcceptEncoding) &&
                    (AcceptEncoding.Contains("gzip") || AcceptEncoding.Contains("deflate")))
                return true;
            return false;
        }

        /// <summary>
        /// Sets up the current page or handler to use GZip through a Response.Filter
        /// IMPORTANT:
        /// You have to call this method before any output is generated!
        /// </summary>
        public static void GZipEncodePage()
        {
            HttpResponse Response = HttpContext.Current.Response;

            if (IsGZipSupported())
            {
                string AcceptEncoding = HttpContext.Current.Request.Headers["Accept-Encoding"];

                if (AcceptEncoding.Contains("deflate"))
                {
                    Response.Filter = new System.IO.Compression.DeflateStream(Response.Filter,
                                               System.IO.Compression.CompressionMode.Compress);
                    #region II6不支持此方法,(实际上此值默认为null 也不需要移除)
                    //Response.Headers.Remove("Content-Encoding");
                    #endregion
                    Response.AppendHeader("Content-Encoding", "deflate");
                }
                else
                {
                    Response.Filter = new System.IO.Compression.GZipStream(Response.Filter,
                                                 System.IO.Compression.CompressionMode.Compress);
                    #region II6不支持此方法,(实际上此值默认为null 也不需要移除)
                    //Response.Headers.Remove("Content-Encoding");
                    #endregion
                    Response.AppendHeader("Content-Encoding", "gzip");
                }
            }

            // Allow proxy servers to cache encoded and unencoded versions separately
            Response.AppendHeader("Vary", "Content-Encoding");
        }
    }

    /// <summary>
    /// 强制Defalte压缩
    /// Content-encoding:gzip，Content-Type:application/json
    /// DEFLATE是一个无专利的压缩算法，它可以实现无损数据压缩，有众多开源的实现算法。
    /// </summary>
    public class DeflateCompressionAttribute : ActionFilterAttribute
    {
        public override void OnActionExecuting(HttpActionContext filterContext)
        {
            HttpResponse Response = HttpContext.Current.Response;
            Response.Filter = new System.IO.Compression.DeflateStream(Response.Filter,
                                              System.IO.Compression.CompressionMode.Compress);
            #region II6不支持此方法,(实际上此值默认为null 也不需要移除)
            //Response.Headers.Remove("Content-Encoding");
            #endregion
            Response.AppendHeader("Content-Encoding", "deflate");
        }

        //public override void OnActionExecuted(HttpActionExecutedContext actContext)
        //{
        //    var content = actContext.Response.Content;
        //    var bytes = content == null ? null : content.ReadAsByteArrayAsync().Result;
        //    var zlibbedContent = bytes == null ? new byte[0] :
        //    APP.Core.Utility.ZHelper.DeflateByte(bytes);
        //    actContext.Response.Content = new ByteArrayContent(zlibbedContent);
        //    actContext.Response.Content.Headers.Remove("Content-Type");
        //    actContext.Response.Content.Headers.Add("Content-encoding", "deflate");
        //    actContext.Response.Content.Headers.Add("Content-Type", "application/json");
        //    base.OnActionExecuted(actContext);
        //}
    }

    /// <summary>
    /// 强制GZip压缩，application/json
    /// Content-encoding:gzip，Content-Type:application/json
    /// GZIP是使用DEFLATE进行压缩数据的另一个压缩库
    /// </summary>
    public class GZipCompressionAttribute : ActionFilterAttribute
    {
        public override void OnActionExecuting(HttpActionContext filterContext)
        {
            HttpResponse Response = HttpContext.Current.Response;
            Response.Filter = new System.IO.Compression.GZipStream(Response.Filter,
                                              System.IO.Compression.CompressionMode.Compress);
            #region II6不支持此方法,(实际上此值默认为null 也不需要移除)
            //Response.Headers.Remove("Content-Encoding");
            #endregion
            Response.AppendHeader("Content-Encoding", "gzip");
        }

        //public override void OnActionExecuted(HttpActionExecutedContext actContext)
        //{
        //    var content = actContext.Response.Content;
        //    var bytes = content == null ? null : content.ReadAsByteArrayAsync().Result;
        //    var zlibbedContent = bytes == null ? new byte[0] :
        //    APP.Core.Utility.ZHelper.GZipByte(bytes);
        //    actContext.Response.Content = new ByteArrayContent(zlibbedContent);
        //    actContext.Response.Content.Headers.Remove("Content-Type");
        //    actContext.Response.Content.Headers.Add("Content-encoding", "gzip");
        //    actContext.Response.Content.Headers.Add("Content-Type", "application/json");
        //    base.OnActionExecuted(actContext);
        //}
    }
}